﻿using ChatGPT.Dto;
using ChatGPT.Repository;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
using OpenAI.GPT3.Interfaces;
using OpenAI.GPT3.ObjectModels;
using OpenAI.GPT3.ObjectModels.RequestModels;
using System.Text;

namespace ChatGPT.Controllers;

/// <summary>
/// </summary>
[Route("Chat/[controller]")]
[ApiController]
public class HomeController : ControllerBase
{
    private readonly IMongoRepository<ChatLog> _mongoRepository;
    private readonly IOpenAIService _openAIService;

    public HomeController(IOpenAIService openAIService
        , IMongoRepository<ChatLog> mongoRepository)
    {
        _openAIService = openAIService;
        _mongoRepository = mongoRepository;
    }

    /// <summary>
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost("query")]
    public async Task Query(ChatGptQueryDto input)
    {
        Response.ContentType = "text/event-stream";
        //for (var i = 0; i < 10; i++)
        //{
        //    var data = $"uid:{input.UserId}\n"
        //        + $"query:{input.Query}\n";
        //    var bytes = Encoding.UTF8.GetBytes(data);
        //    await Response.Body.WriteAsync(bytes);
        //    await Response.Body.FlushAsync();
        //    await Task.Delay(2000);
        //}
        var filterBuilder = Builders<ChatLog>.Filter;
        var filter = filterBuilder.Gt("CreateTime", DateTime.Now.AddHours(-12)) & filterBuilder.Eq(x => x.UserId, input.UserId);
        var sort = Builders<ChatLog>.Sort.Descending(x => x.CreateTime);
        var content = _mongoRepository.Find(filter, sort).Select(x => new ChatMessage(x.Role, x.Content)).Take(10).ToList();
        content.Add(new ChatMessage("user", input.Query));
        await _mongoRepository.AddAsync(new ChatLog { UserId = input.UserId, Role = "user", Content = input.Query, CreateTime = DateTime.Now });

        var completions = _openAIService.ChatCompletion.CreateCompletionAsStream(new ChatCompletionCreateRequest()
        {
            Messages = content
        }, Models.ChatGpt3_5Turbo);

        StringBuilder sb = new();
        await foreach (var completionResponse in completions)
        {
            if (completionResponse.Successful)
            {
                var message = completionResponse.Choices[0].Message.Content;
                if (string.IsNullOrEmpty(message))
                    continue;
                sb.Append(message);
                var data = $"{message}\n\n";
                var bytes = Encoding.UTF8.GetBytes(data);
                await Response.Body.WriteAsync(bytes);
                await Response.Body.FlushAsync();
            }
            else
                break;
        }
        await _mongoRepository.AddAsync(new ChatLog { UserId = input.UserId, Role = "assistant", Content = sb.ToString(), CreateTime = DateTime.Now });
        Response.Body.Close();
    }
}